﻿namespace Koala.Pro.Common
{
    public static class ExtConvert
    {
        public static int ToInt(this object data)
        {
            if (data == null)
            {
                return 0;
            }
            if (int.TryParse(data.ToString(), out var result))
            {
                return result;
            }
            try
            {
                return Convert.ToInt32(ToDouble(data, 0));
            }
            catch (Exception)
            {
                return 0;
            }
        }

        public static int? ToIntOrNull(this object data)
        {
            if (data == null)
            {
                return null;
            }
            if (int.TryParse(data.ToString(), out var result))
            {
                return result;
            }
            return null;
        }

        public static double ToDouble(this object data)
        {
            if (data == null)
            {
                return 0.0;
            }
            if (!double.TryParse(data.ToString(), out var result))
            {
                return 0.0;
            }
            return result;
        }

        public static double ToDouble(this object data, int digits)
        {
            return Math.Round(ToDouble(data), digits);
        }

        public static double? ToDoubleOrNull(this object data)
        {
            if (data == null)
            {
                return null;
            }
            if (double.TryParse(data.ToString(), out var result))
            {
                return result;
            }
            return null;
        }

        public static decimal ToDecimal(this object data)
        {
            if (data == null)
            {
                return 0m;
            }
            if (!decimal.TryParse(data.ToString(), out var result))
            {
                return 0m;
            }
            return result;
        }

        public static decimal ToDecimal(this object data, int digits)
        {
            return Math.Round(ToDecimal(data), digits);
        }

        public static decimal? ToDecimalOrNull(this object data)
        {
            if (data == null)
            {
                return null;
            }
            if (decimal.TryParse(data.ToString(), out var result))
            {
                return result;
            }
            return null;
        }

        public static decimal? ToDecimalOrNull(this object data, int digits)
        {
            decimal? num = ToDecimalOrNull(data);
            if (!num.HasValue)
            {
                return null;
            }
            return Math.Round(num.Value, digits);
        }

        public static DateTime ToDate(this object data)
        {
            if (data == null)
            {
                return DateTime.MinValue;
            }
            if (!DateTime.TryParse(data.ToString(), out var result))
            {
                return DateTime.MinValue;
            }
            return result;
        }

        public static DateTime? ToDateOrNull(this object data)
        {
            if (data == null)
            {
                return null;
            }
            if (DateTime.TryParse(data.ToString(), out var result))
            {
                return result;
            }
            return null;
        }

        public static bool ToBool(this object data)
        {
            if (data == null)
            {
                return false;
            }
            bool? @bool = GetBool(data);
            if (@bool.HasValue)
            {
                return @bool.Value;
            }
            bool result;
            return bool.TryParse(data.ToString(), out result) && result;
        }

        private static bool? GetBool(this object data)
        {
            return data.ToString().Trim().ToLower() switch
            {
                "0" => false,
                "1" => true,
                "是" => true,
                "否" => false,
                "yes" => true,
                "no" => false,
                _ => null,
            };
        }

        public static bool? ToBoolOrNull(this object data)
        {
            if (data == null)
            {
                return null;
            }
            bool? @bool = GetBool(data);
            if (@bool.HasValue)
            {
                return @bool.Value;
            }
            if (bool.TryParse(data.ToString(), out var result))
            {
                return result;
            }
            return null;
        }

        public static string ToString(this object data)
        {
            if (data != null)
            {
                return data.ToString().Trim();
            }
            return string.Empty;
        }

        public static T SafeValue<T>(this T? value) where T : struct
        {
            return value.GetValueOrDefault();
        }

        public static bool IsEmpty(this string value)
        {
            return string.IsNullOrWhiteSpace(value);
        }

        public static bool IsEmpty(this Guid? value)
        {
            if (!value.HasValue)
            {
                return true;
            }
            return IsEmpty(value.Value);
        }

        public static bool IsEmpty(this Guid value)
        {
            if (value == Guid.Empty)
            {
                return true;
            }
            return false;
        }

        public static bool IsEmpty(this object value)
        {
            if (value != null && !string.IsNullOrEmpty(value.ToString()))
            {
                return false;
            }
            return true;
        }

        public static bool IsNullOrEmpty(this object obj)
        {
            if (obj == null)
            {
                return true;
            }
            return string.IsNullOrEmpty(obj.ToString());
        }
    }
}
